#include <string.h>

#include "func.h"

#define IS_SPACE(x) ((x)==' '||(x)=='\r'||(x)=='\n'||(x)=='\f'||(x)=='\b'||(x)=='\t')

void trim ( std::string& str )
{
    if ( str.empty() ) return;

    size_t len = str.length();
    size_t b = 0;
    size_t e = len;
    const char* p = str.c_str();

    for ( size_t i = 0; i < len; ++i ) 
    {
        if ( IS_SPACE(p[i]) ) b = i+1;
        else break;
    }
    for ( size_t i = len - 1; i > 0 && i > b; --i )
    {
        if ( IS_SPACE(p[i]) ) e = i;
        else break;
    }

    if ( b == len || 0 == e || b >= e ) 
    {
        str.clear();
        return;
    }

    str = str.substr ( b, e-b );
}

bool contains ( const std::string& src, const std::string& dest )
{
	return std::string::npos != src.find(dest);
}


void split ( std::vector<std::string>& vec, const std::string& src, char dim, bool delempty )
{
    vec.clear();
    //if ( src.empty() ) vec.push_back ( src );

    size_t prev = 0;
    size_t len = src.length();
    const char* p = src.c_str();

    for ( size_t i = 0; i < len; ++i )
    {
        if ( p[i] == dim )
        {
            if ( !delempty || i > prev ) vec.push_back ( src.substr ( prev, i-prev ) );
            prev = i+1;
        }
    }
    if ( !delempty || len > prev ) vec.push_back ( src.substr ( prev, len-prev ) );
}

void split ( std::vector<std::string>& vec, const std::string& src, const char* dim, bool delempty )
{
    vec.clear();
    //if ( src.empty() ) vec.push_back ( src );

    size_t len = strlen(dim);
    size_t sp = 0;
    size_t pos = src.find ( dim );
    while ( std::string::npos != pos )
    {
        if ( !delempty || sp < pos ) vec.push_back ( src.substr ( sp, pos-sp ) );
        sp = pos + len;
        pos = src.find ( dim, sp );
    }
    if ( !delempty || sp < src.length() ) vec.push_back ( src.substr ( sp ) );
}

void replace_all ( std::string& str, const std::string& from, const std::string& to )
{
    size_t f_len = from.length();
    size_t t_len = to.length();
    size_t pos = str.find ( from );
    while ( std::string::npos != pos )
    {
        str.replace ( pos, f_len, to );
        pos = str.find ( from, pos+t_len );
    }
}

void to_upper ( std::string& str )
{
    size_t len = str.length();
    char* p = (char*)str.c_str();

    for ( size_t i = 0; i < len; ++i )
    {
        if ( 'a' <= p[i] && 'z' >= p[i] )
            p[i] -= 32;
    }
}

void to_lower ( std::string& str )
{
    size_t len = str.length();
    char* p = (char*)str.c_str();

    for ( size_t i = 0; i < len; ++i )
    {
        if ( 'A' <= p[i] && 'Z' >= p[i] )
            p[i] += 32;
    }
}

int transform ( const std::string& str, int type )
{
    if ( str.empty() ) return 0;

    char *endptr = NULL;
    errno = 0;

    long int v = strtol ( str.c_str(), &endptr, 10 );
    if ( *endptr || errno )
    {
        throw std::logic_error ( "Invalid type transform!" );
    }
    return (int)v;
}

int64_t transform ( const std::string& str, int64_t type )
{
    if ( str.empty() ) return 0;

    char *endptr = NULL;
    errno = 0;

    long long int v = strtoll ( str.c_str(), &endptr, 10 );
    if ( *endptr || errno )
    {
        throw std::logic_error ( "Invalid type transform!" );
    }
    return v;
}

unsigned transform ( const std::string& str, unsigned type )
{
    if ( str.empty() ) return 0;

    char *endptr = NULL;
    errno = 0;

    unsigned v = strtoul ( str.c_str(), &endptr, 10 );
    if ( *endptr || errno )
    {
        throw std::logic_error ( "Invalid type transform!" );
    }
    return v;
}

uint64_t transform ( const std::string& str, uint64_t type )
{
    if ( str.empty() ) return 0;

    char *endptr = NULL;
    errno = 0;

    long long unsigned v = strtoull ( str.c_str(), &endptr, 10 );
    if ( *endptr || errno )
    {
        throw std::logic_error ( "Invalid type transform!" );
    }
    return v;
}

double transform ( const std::string& str, double type )
{
    if ( str.empty() ) return 0;

    char *endptr = NULL;
    errno = 0;

    double v = strtod ( str.c_str(), &endptr );
    if ( *endptr || errno )
    {
        throw std::logic_error ( "Invalid type transform!" );
    }
    return v;
}

